package com.fxnotes.common.ui;

import java.util.*;
import javafx.scene.Parent;

public abstract class Controller <T extends Controller> {

    protected String name;
    protected Map<String, T> controllers = new LinkedHashMap<>();
    protected Map<String, NodePresenter<Parent>> presenters = new LinkedHashMap<>();

    public Controller(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void addController(T controller) {
        controllers.put(controller.getName(), controller);
    }

    public void addControllers(Collection<T> controllers) {
        for (T controller : controllers) {
            addController(controller);
        }
    }

    public void addPresenter(NodePresenter<Parent> presenter) {
        presenters.put(presenter.getName(), presenter);
    }

    public boolean isValidPath(NavigationPath path) {
        if (!path.isLeaf()) {
            return checkControllers(path);

        } else {
            return checkPresenters(path);
        }
    }

    private boolean checkControllers(NavigationPath path) {
        if (controllers.containsKey(path.head())) {
            return controllers.get(path.head()).isValidPath(path.tail());

        } else {
            return false;
        }
    }

    private boolean checkPresenters(NavigationPath path) {
        return presenters.containsKey(path.head());
    }

    public void showPath(NavigationPath path) {
        if (!path.isLeaf()) {
            showController(path);

        } else {
            showPresenter(path);
        }
    }

    private void showController(NavigationPath path) {
        if (controllers.containsKey(path.head())) {
            Controller controller = controllers.get(path.head());
            controller.showPath(path.tail());
            onControllerChanged(controller);
        }
    }

    private void showPresenter(NavigationPath path) {
        if (presenters.containsKey(path.head())) {
            onPresenterChanged(presenters.get(path.head()));
        }
    }

    protected void onControllerChanged(Controller module) {
    }

    protected void onPresenterChanged(NodePresenter<Parent> nodePresenter) {
    }
}
